#include "constructora.h"
#include <iostream>
#include <sstream>
#include <string>
#include <cassert>
#include <cstdlib>
using namespace std;


void asegurar(const multiconj_stock& ms, string s){
    ostringstream out;
    ms.mostrar(out);
    string t = out.str();
    if(s != t){
        cerr << s << "!=" << t << endl;
        assert(false);
    }
}

template <typename T>
void asegurar(const Lista<T>& l, string s){
    ostringstream out;
    l.mostrarLista(out);
    string t = out.str();
    if(s != t){
        cerr << s << "!=" << t << endl;
        assert(false);
    }
}

void asegurar(const Multiconj_materiales& mm, string s) {
	ostringstream out;
	mm.mostrarMulticonj_materiales(out);
	string t = out.str();
	if (s != t) {
		cerr << s << " != " << t << endl;
		assert(false);
	}
}

void Test() {
	Multiconj_materiales mm1;
	mm1.agregar(5,5);
	mm1.agregar(4,9);
	Multiconj_materiales mm2;
	mm2.agregar(2,23);
	Multiconj_materiales mm3;
	mm3.agregar(3,7);
	mm3.agregar(4,8);
	Catalogo c;
	c.agregarVivienda(mm1);
	c.agregarVivienda(mm2);
	c.agregarVivienda(mm3);
	constructora constr = constructora(c);
	assert(3==constr.catalogo().cantidadViviendas());
	assert(constr.stock().vacio());
	assert(6==constr.stock().cantMateriales());
	assert(constr.deuda().vacio());
	constr.comprar(2,50);
	//STOCK: (2,50) - DEUDA: 0 - PENDIENTES: -
	assert(50==constr.stock().cardinal(2));
	constr.construir(1);
	assert(27==constr.stock().cardinal(2));
	//STOCK: (2,27) - DEUDA: 0 - PENDIENTES: -
	assert(constr.deuda().vacio());
	constr.construir(0);
	//STOCK: (2,27) - DEUDA: (5,5) Y (4,9) - PENDIENTES: -
	asegurar(constr.deuda(),"[<5;5>,<4;9>]");
	assert(constr.pendientes().cola().esVacia());
	constr.construir(0);
	//STOCK: (2,27) - DEUDA: (5,5) Y (4,9) - PENDIENTES: (0)
	assert(0==constr.pendientes().cola().primero());
	constr.comprar(5,50);
	//STOCK: (2,27) Y (5,45) - DEUDA: (4,9) - PENDIENTES: (0)
	asegurar(constr.deuda(),"[<4;9>]");
	assert(45==constr.stock().cardinal(5));
	assert(0==constr.pendientes().cola().primero());
	constr.comprar(4,9);
	//STOCK: (2,27) Y (5,40) - DEUDA: (4,9) - PENDIENTES: -
	asegurar(constr.deuda(),"[<4;9>]");
	assert(40==constr.stock().cardinal(5));
	assert(constr.pendientes().cola().esVacia());
	constr.comprar(4,9);
	//STOCK: (2,27) Y (5,40) - DEUDA: 0 - PENDIENTES: -
	assert(constr.deuda().vacio());
	assert(0==constr.stock().cardinal(4));
	constr.construir(2);
	//STOCK: (2,27) Y (5,40) - DEUDA: (3,7) Y (4,8) - PENDIENTES: -
	asegurar(constr.deuda(),"[<3;7>,<4;8>]");
	constr.construir(0);
	//STOCK: (2,27) Y (5,40) - DEUDA: (3,7) Y (4,8) - PENDIENTES: (0)
	asegurar(constr.deuda(),"[<3;7>,<4;8>]");
	constr.construir(1);
	//STOCK: (2,4) Y (5,40) - DEUDA: (3,7) Y (4,8) - PENDIENTES: (0)
	asegurar(constr.deuda(),"[<3;7>,<4;8>]");
	constr.construir(1);
	//STOCK: (2,4) Y (5,40) - DEUDA: (3,7) Y (4,8) - PENDIENTES: (0,1)
	asegurar(constr.deuda(),"[<3;7>,<4;8>]");
	constr.construir(2);
	//STOCK: (2,4) Y (5,40) - DEUDA: (3,7) Y (4,8) - PENDIENTES: (0,1,2)
	asegurar(constr.deuda(),"[<3;7>,<4;8>]");
	asegurar(constr.pendientes().cola(), "[0,1,2]");
	constr.comprar(3,15);
	//STOCK: (2,4), (5,40) Y (3,8) - DEUDA: (4,8) - PENDIENTES: (0,1,2)
	asegurar(constr.deuda(),"[<4;8>]");
	asegurar(constr.pendientes().cola(), "[0,1,2]");
	constr.comprar(4,16);
	//STOCK: (2,4), (5,35), (3,8) - DEUDA: (4,1) - PENDIENTES: (1,2)
	asegurar(constr.deuda(),"[<4;1>]");
	asegurar(constr.pendientes().cola(), "[1,2]");
	constr.construir(0);
	//STOCK: (2,4), (5,35), (3,8) - DEUDA: (4,1) - PENDIENTES: (1,2,0)
	asegurar(constr.pendientes().cola(), "[1,2,0]");
	constr.construir(2);
	//STOCK: (2,4), (5,35) Y (3,8) - DEUDA: (4,1) - PENDIENTES: (1,2,0,2)
	asegurar(constr.pendientes().cola(), "[1,2,0,2]");
	constr.comprar(4,9);
	//STOCK: (5,35), (3,1) - DEUDA: (2,19) - PENDIENTES: (0,2)
	asegurar(constr.pendientes().cola(), "[0,2]");
	asegurar(constr.deuda(),"[<2;19>]");
	constr.comprar(3,80);
	//STOCK: (5,35), (3,81) - DEUDA: (2,19) - PENDIENTES: (0,2)
	constr.comprar(4,8);
	//STOCK: (5,35), (3,74) - DEUDA: (2,19) - PENDIENTES: (0)
	asegurar(constr.pendientes().cola(), "[0]");
	asegurar(constr.deuda(),"[<2;19>]");
	constr.donar();
	//STOCK: (5,35), (3,60) - DEUDA: (2,19) - PENDIENTES: (0)
	assert(60==constr.stock().cardinal(3));
	asegurar(constr.pendientes().cola(), "[0]");
	asegurar(constr.deuda(),"[<2;19>]");
	constr.comprar(4,80);
	//STOCK: (5,30), (3,60) Y (4,71) - DEUDA: (2,19) - PENDIENTES: -
	assert(constr.pendientes().cola().esVacia());
	asegurar(constr.deuda(),"[<2;19>]");
	constr.donar();
	assert(57==constr.stock().cardinal(4));
	//STOCK: (5,30), (3,60) Y (4,57) - DEUDA: (2,19) - PENDIENTES: -
	constr.donar();
	assert(48==constr.stock().cardinal(3));
	//STOCK: (5,30), (3,48) Y (4,57) - DEUDA: (2,19) - PENDIENTES: -
	asegurar(constr.stock(), "[0->0, 1->0, 2->0, 3->48, 4->57, 5->30]");
}

#define RUNTEST(t) { cerr << "Corriendo test " << #t << endl; t (); cerr << "Terminado test " << #t << endl; }

int main() {
	RUNTEST (Test); 
}
